# Sass 中的数据类型(值类型)
Number, 可以是有单位或没有单位的值, 比如
12
或100px
。String, 可以是有引号或没有引号的值, 比如
"Helvetica Neue"
或bold
。Color, 可以通过十六进制表示或名称引用,如
#c6538c
或blue
,或从函数返回,如rgb(107, 113, 127)
或hsl(210, 100%, 20%)
。List, 必须用空格或逗号隔开,可以用方括号
[]
括起, 也可以不用, 比如1.5em 1em 0 2em
,Helvetica, Arial, sans-serif
, 或是[col1-start]
.
Sass 特有的值类型:
Boolean ,
true
或false
null
Map 键值对映射,圆括号包裹, 比如
("background": red, "foreground": pink)
。Function , 由
get-function()
返回并由call()
调用的函数引用。
# Number
Sass 中的数字有两个组成部分:数字本身和它的单位。例如,在 16px
中,数字是 16
,单位是 px
。数字可以没有单位,也可以有复杂的单位。
$num1: 100; // 100
$num2: 0.8; // 0.8
$num3: 16px; // 16px
$num4: 5px * 2px; // 10px*px (read "square pixels")
2
3
4
Sass 中的数字支持与 CSS 数字相同的格式,包括科学记数法,它在数字和它的 10 的幂之间用 e
书写。由于浏览器中对科学符号的支持一直不稳定,所以 Sass 总是将其编译为完全扩展的数字。
$num1: 5.2e3; // 5200
$num2: 6e-2; // 0.06
2
注意:Sass 不区分整数和小数,所以例如 5 / 2
返回 2.5
而不是 2
。这与JavaScript的行为相同,但与许多其他编程语言不同。
# 单位
Sass 对单位的操作是基于现实世界的单位计算的。当两个数相乘时,它们的单位也相乘。当一个数除以另一个数时,结果取第一个数的分子单位和第二个数的分母单位。一个数的分子和/或分母可以有任意数量的单位。
$num1: 4px * 6px; // 24px*px (read "square pixels")
$num2: 5px / 2s; // 2.5px/s (read "pixels per second")
$num3: 5px * 30deg / 2s / 24em; // 3.125px*deg/s*em (read "pixel-degrees per second-em")
$num4: 20deg / 1s; // 20deg/s
$num5: 1 / $num4; // 0.05s/deg
2
3
4
5
但是,CSS 是不支持像 square pixels
这样的复杂单位,使用带有复杂单位的数字作为属性值将会产生错误。如果没有得到正确的单位,这通常意味着你的计算出了问题。
可以使用 @debug
规则来检查任何变量或表达式的单位。
Sass 将在兼容的单元之间自动转换,尽管它将为结果选择哪个单元取决于您使用的 Sass 的哪个实现版本。如果你试图组合不兼容的单位,比如 1in + 1em
, Sass将抛出一个错误。
// CSS defines one inch as 96 pixels.
@debug 1in + 6px; // 102px or 1.0625in
@debug 1in + 1s;
// ^^^^^^^^
// Error: Incompatible units s and in.
2
3
4
5
在现实世界的单位计算中,如果分子包含与分母单位兼容的单位(如 96px / 1in
),它们就会抵消。
$num1: (96px / 1in); // 1
注意,要避免使用像 #{$number}px
这样的插值。这实际上并没有创建一个数字,它创建了一个看起来像数字的无引号字符串,但不能用于任何数字操作或函数。定义 $number
变量时可以带上单位 px
,或者写为 $number * 1px
。
Sass 的百分比和其他单位一样。它们不能与小数互换,因为在 CSS 中小数和百分比表示不同的东西。例如,50%
是一个以 %
为单位的数字,Sass 认为它与 0.5
不同。
可以使用单位算术在小数和百分比之间进行转换。$percentage / 100%
将返回相应的小数,而$decimal * 100%
将返回相应的百分比。还可以使用 math.percentage()
函数作为 $decimal * 100%
的更显式的写法。
# 精度(Precision)
Sass 数字支持小数点后最多 10 位的精度。这意味着:
- 生成的 CSS 只包含小数点后的数字的前 10 位。
- 像
==
和>=
这样的运算,如果两个数字在小数点之后的前 10 位都是相同的,则认为它们是相等的,小数点之后 10 位以上数字直接被忽略。 - 如果一个数字与一个整数的距离小于0.0000000001,对于像
list.nth()
这样需要整数参数的函数来说,它被认为是一个整数。
$num1: 0.012345678912345; // 0.0123456789
$num2: 0.01234567891 == 0.01234567899; // true
$num3: 1.00000000009; // 1
$num4: 0.99999999991; // 1
2
3
4
# String
字符串是字符序列(Unicode 码位)。Sass 支持两种内部结构相同但呈现方式不同的字符串:带引号的字符串,如 "Helvetica Neue"
,以及不带引号的字符串(也称为标识符),如 bold
。
可以使用 string.unquote()
函数将带引号的字符串转换为不带引号的字符串,也可以使用 string.quote()
函数将不带引号的字符串转换为带引号的字符串。
@use "sass:string";
@debug string.unquote(".widget:hover"); // .widget:hover
@debug string.quote(bold); // "bold"
2
3
4
# 转义(Escapes)
所有 Sass 字符串都支持标准的 CSS 转义码:
- 除了所有字母和数字以外之外的任何字符都可以通过在前面写
\
来作为字符串的一部分 - 任何字符都可以作为字符串的一部分,方法是在
\
后面加上十六进制 Unicode 码,不同字符的 Unicode 码用空格分隔。
@debug "\""; // '"'
@debug \.widget; // \.widget
@debug "\a"; // 一个不可见的换行符
@debug "line1\a line2"; // "line1换行line2"
@debug "Nat + Liz \1F46D"; // "Nat + Liz 👭"
2
3
4
5
# 带引号的 string
带引号的字符串写在单引号或双引号之间,如 "Helvetica Neue"
。可以包含插值,以及任何未转义的字符,除了:
\
, 需要使用\\
来转义;'
或"
, 需要使用\'
或\"
来转义- 换行, 需要写为
\a
并加一个空格与后面的内容隔开
带引号的字符串保证被编译成与原始 Sass 字符串内容相同的 CSS 字符串。
@debug "Helvetica Neue"; // "Helvetica Neue"
@debug "C:\\Program Files"; // "C:\\Program Files"
@debug "\"Don't Fear the Reaper\""; // "\"Don't Fear the Reaper\""
@debug "line1\a line2"; // "line1\a line2"
$roboto-variant: "Mono";
@debug "Roboto #{$roboto-variant}"; // "Roboto Mono"
2
3
4
5
6
7
8
带引号的字符串放入插值中时,它的引号将被删除。这使得编写包含选择器的字符串变得很容易,例如,选择器可以被注入到样式规则中,而不需要添加引号。
# 不带引号的字符串
不带引号的字符串就是写 CSS 标识符。它们可能包括任何地方的插值。
@debug bold; // bold
@debug -webkit-flex; // -webkit-flex
@debug --123; // --123
$prefix: ms;
@debug -#{$prefix}-flex; // -ms-flex
2
3
4
5
6
7
当然,并不是所有的标识符都被解析为不带引号的字符串:
- CSS 颜色名称被解析为 color 类型。
null
被解析为 Sass 的null
值。true
和false
被解析为 boolean 类型。not
,and
,or
被解析为 boolean 操作符
正因为如此,除非您专门编写使用不带引号的字符串的 CSS 属性值,否则编写带引号的字符串通常是一个好主意。
当解析未加引号的字符串时,转义的文字文本将作为字符串的一部分进行解析。例如,\a
被解析为字符\
、a
和 空格
。为了确保在CSS中具有相同含义的未加引号的字符串以相同的方式解析,这些转义都是规范化的。对于每个代码点,不管是转义的还是未转义的:
- 如果它是一个有效的标识符字符,它将不转义地包含在未加引号的字符串中。例如,
\1F46D
返回未加引号的字符串👭
。 - 如果它是除换行符或制表符之外的可打印字符,则它包含在
\
之后。例如,\21
返回未加引号的字符串\!
。 - 否则,小写 Unicode 转义将包含在末尾的空格中。例如,
\7Fx
返回未加引号的字符串\7f x
。
@use "sass:string";
@debug \1F46D; // 👭
@debug \21; // \!
@debug \7Fx; // \7f x
@debug string.length(\7Fx); // 5
2
3
4
5
6
# 字符串的索引
Sass有许多字符串函数,它们接受或返回数字作为索引,这些数字指的是字符串中的字符。
Sass 的字符串中第一个字符的索引为 1
,不同于大多数语言索引从 0
开始。
-1
表示字符串中的最后一个字符,-2
表示倒数第二个字符,以此类推。
@use "sass:string";
@debug string.index("Helvetica Neue", "Helvetica"); // 1
@debug string.index("Helvetica Neue", "Neue"); // 11
@debug string.slice("Roboto Mono", -4); // "Mono"
2
3
4
5
# Color
Sass 颜色可以写成:
- 十六进制代码, 比如
#f2ece4
,或者包含透明值的#b37399aa
- CSS 颜色名称, 比如
midnightblue
,transparent
- 函数, 比如
rgb()
、rgba()
、hsl()
和hsla()
。
@debug #f2ece4; // #f2ece4
@debug #b37399aa; // rgba(179, 115, 153, 67%)
@debug midnightblue; // #191970
@debug rgb(204, 102, 153); // #c69
@debug rgba(107, 113, 127, 0.8); // rgba(107, 113, 127, 0.8)
@debug hsl(228, 7%, 86%); // #dadbdf
@debug hsla(20, 20%, 85%, 0.7); // rgb(225, 215, 210, 0.7)
2
3
4
5
6
7
Sass 支持许多有用的 color 函数来在现有颜色的基础上创建新的颜色。可以通过混合颜色或缩放颜色的色相、饱和度或明度。详情参考内置模块章节。
$venus: #998099;
@debug scale-color($venus, $lightness: +15%); // #a893a8
@debug mix($venus, midnightblue); // #594d85
2
3
4
# List
列表包含其他值的序列。在 Sass 中,列表中的元素可以用逗号分隔,如 Helvetica, Arial, sans-serif
,或空格分隔,如 10px 15px 0 0
,但不能混合使用空格和逗号。
与大多数其他语言不同,Sass 中的列表不需要特殊的方括号,任何用空格或逗号分隔的表达式都可以算作一个列表。当然,也允许使用方括号来编写列表,如 [a b]
或 [a, b]
。这对使用 grid-template-columns
来说是非常有用的。
Sass 列表可以包含任意个元素,甚至是包括 0 个。单元素列表可以写成 (a,)
或 [a]
,零元素列表可以写成 ()
或 []
。此外,对待一个单独存在的不在列表中的值,所有内置的列表函数都将他们视为列表,比如 a
对列表函数来说就像是 (a)
或 [a]
似的,这意味着不需要显式地创建像 (a)
或 [a]
这样的单个元素的列表。
$border1: (1px solid #f00);
$border2: (1px, solid, #f00);
$border3: [1px solid #f00];
$border4: [1px, solid, #f00];
.div1 {
border: $border1;
}
.div2 {
border: $border2;
}
.div3 {
border: $border3;
}
.div4 {
border: $border4;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
编译后的 css :
.div1 {
border: 1px solid #f00;
}
.div2 {
border: 1px, solid, #f00;
}
.div3 {
border: [1px solid #f00];
}
.div4 {
border: [1px, solid, #f00];
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 索引
Sass 的列表中第一个元素的索引为 1
,不同于大多数语言索引从 0
开始。
-1
表示列表中的最后一个元素,-2
表示倒数第二个元素,以此类推。
# 访问某个元素
使用 list.nth($list, $index)
函数获取一个列表中的值,第一个参数表示列表,第二个参数表示要获取元素的索引。
@use 'sass:list';
@debug list.nth(10px 12px 16px, 2); // 12px
@debug list.nth([line1, line2, line3], -1); // line3
2
3
4
# 遍历列表
使用 @each $ele in $list
语句来遍历一个列表, $ele
表示当前循环的列表元素, $list
表示要遍历的列表。
$sizes: 40px, 50px, 80px;
@each $size in $sizes {
.icon-#{$size} {
font-size: $size;
height: $size;
width: $size;
}
}
2
3
4
5
6
7
8
9
编译后的 css :
.icon-40px {
font-size: 40px;
height: 40px;
width: 40px;
}
.icon-50px {
font-size: 50px;
height: 50px;
width: 50px;
}
.icon-80px {
font-size: 80px;
height: 80px;
width: 80px;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 追加元素
使用 list.append($list, $val)
函数,第一个参数为目标列表,第二个参数为要追加的元素,并返回一个在末尾追加了新元素的的新的列表。注意,因为 Sass 列表是不可变的,所以它不会修改原始列表。
@use 'sass:list';
@debug list.append(10px 12px 16px, 25px); // 10px 12px 16px 25px
@debug list.append([col1-line1], col1-line2); // [col1-line1, col1-line2]
2
3
4
# 查找元素的索引
使用 list.index($list, $value)
函数,第一个参数为目标列表,第二个参数为目标元素,找到元素返回索引值,找不到返回 null
。
@use 'sass:list';
@debug list.index(1px solid red, 1px); // 1
@debug list.index(1px solid red, solid); // 2
@debug list.index(1px solid red, dashed); // null
2
3
4
5
# 列表的不可变性(Immutability)
Sass 中的列表是不可变的,这意味着列表值的内容永远不会改变。Sass 的列表函数只能返回一个新的列表,而不是修改原始列表。
不可变性有助于在各个地方共用一个列表时,避免因为列表被更改而出现一些 Bug。
所以,如果一个变量表示的列表需要修改,应该将新的列表赋值给这个变量。
@use 'sass:list';
$list: (10px 12px 16px);
$list: list.append($list, 25px);
@debug $list; // 10px 12px 16px 25px
2
3
4
5
6
7
# 参数列表
当你声明一个接收任意参数的 mixin 或 function 时,任意参数这个变量将会是一个特殊的列表,称为 参数列表 。这个变量就像是一个列表,包含传递给 mixin 或 function 的所有参数,
如果用户传递的关键字参数,可以将参数列表传递给 meta.keywords()
函数,将返回一个 map 类型的值。
@use "sass:meta";
@mixin syntax-colors($args...) {
// map 类型的值 (string: #080, comment: #800, variable: #60b)
@debug meta.keywords($args);
@each $name, $color in meta.keywords($args) {
pre span.stx-#{$name} {
color: $color;
}
}
}
@include syntax-colors(
$string: #080,
$comment: #800,
$variable: #60b,
)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
编译后的 css :
pre span.stx-string {
color: #080;
}
pre span.stx-comment {
color: #800;
}
pre span.stx-variable {
color: #60b;
}
2
3
4
5
6
7
8
9
10
11
# Map
map
用来表示键值对的映射,格式为 (key1: value, key2: value)
,其中 key 必须唯一。
$tag: (
"primaryColor": #f00,
"size": 16px
);
$empty: ();
2
3
4
5
6
与列表不同, map 必须用圆括号 ()
括起来。空的 map 写为 ()
。
但是,空列表也是写为 ()
,怎么空的 map 和空列表一样呢?
因为,()
它既是映射又是列表。事实上,所有的 map
都可以算作列表,每个 map 都算是一个包含键值对的列表,每个列表元素就是一组键值对。例如 (a: b, c: d)
表示为 (a b, c d)
。
map 允许使用任何 Sass 值作为它的 key 。 Sass 将会用 ==
操作符来判断两个 key 是否重复。
大多数情况下,强烈推荐使用带引号的字符串作为 map 的 key 。因为有些值,比如颜色名,看起来像未加引号的字符串,但实际上不是字符串而是其他类型。为了避免混乱的问题,字符串作为 key 时都应该加上引号。
由于 map 不是合法的 CSS 值,它们自己不会做很多事情。这就是为什么 Sass 提供了一堆函数来创建 map 并访问它们包含的值。
# 访问 map 的值
通过 map.get($map, $key)
函数来访问值,第一个参数表示 map ,第二个参数表示对应的 key ,指定的 key 不存在时返回 null
。
@use "sass:map";
$font-weights: ("regular": 400, "medium": 500, "bold": 700);
@debug map.get($font-weights, "medium"); // 500
@debug map.get($font-weights, "extra-bold"); // null
2
3
4
5
6
# 遍历 map
通过 @each
语句对一个 map 进行遍历。
$colors: (
"red": #f00,
"green": #0f0,
"blue": #00f,
);
@each $key, $value in $colors {
.icon-#{$key} {
color: $value;
}
}
2
3
4
5
6
7
8
9
10
11
编译后的 css :
.icon-red {
color: #f00;
}
.icon-green {
color: #0f0;
}
.icon-blue {
color: #00f;
}
2
3
4
5
6
7
8
9
10
11
12
# 修改 map
向 map 添加新的键值对或修改已存在的键值对。使用 map.set($map, $key, $value)
函数, 它返回设置完成后的新的 map ,不会修改原 map 。
@use "sass:map";
$colors: (
"red": #f00,
"green": #0f0,
"blue": #00f,
);
@debug map.set($colors, "red", #a11);
// ("red": #a11, "green": #0f0, "blue": #00f)
@debug map.set($colors, "warning", #ff5);
// ("red": #f00, "green": #0f0, "blue": #00f, "warning": #ff5)
2
3
4
5
6
7
8
9
10
11
12
13
# 合并 map
可以使用 map.merge($map1, $map2)
函数合并 map 并返回合并后的新 map 。
@use "sass:map";
$colors: (
"red": #f00,
"green": #0f0,
"blue": #00f,
);
$colors2: (
"yellow": #ff0,
"skyblue": #0ff
);
@debug map.merge($colors, $colors2);
// ("red": #f00, "green": #0f0, "blue": #00f, "yellow": #ff0, "skyblue": #0ff)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 不可变性
和 list 一样,Sass 中的 map 被创建后是不可变的,所以所有的 map 方法都不是直接修改原 map , 而是操作完成后返回一个新的 map 出来。
所以通常应该将新创建的 map 赋值给原变量进行覆盖。
# Function
Sass 本身已经有很多内置的函数可供使用,比如 rgba()
, nth()
, if()
等。
@function
的定义方式和 @mixin
非常类似,但是调用的时候不需要 @include
而是直接调用。
@function my-color () {
@return #f00;
}
.div {
background-color: my-color();
}
2
3
4
5
6
7
@function
与 @mixin
不同之处在于,函数返回的只能是一个值,而不是一段 css 样式代码,也就是说函数返回的结果只能作为变量值或属性值。
# Boolean
布尔值是逻辑值 true
和 false
。除了它们的字面量形式,布尔值还可以由比较运算符和关系操作符以及许多内置函数(如 math.comparable()
和 map. haskey()
)返回。
@use "sass:math";
@debug 1px == 2px; // false
@debug 1px == 1px; // true
@debug 10px < 3px; // false
@debug math.comparable(100px, 3in); // true
2
3
4
5
6
使用 boolean 操作符
@debug true and true; // true
@debug true and false; // false
@debug true or false; // true
@debug false or false; // false
@debug not true; // false
@debug not false; // true
2
3
4
5
6
# 使用布尔值
结合 @if
等操作,可以使用布尔值作出很多不同情况下的操作。
@mixin avatar($size, $circle: false) {
width: $size;
height: $size;
@if $circle {
border-radius: $size / 2;
}
}
.square-av {
@include avatar(100px, $circle: false);
}
.circle-av {
@include avatar(100px, $circle: true);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
或者使用 @if()
函数,类似于三元运算符:
@debug if(true, 10px, 30px); // 10px
@debug if(false, 10px, 30px); // 30px
2
# Truthy 和 Falsy
和其他语言不同的是,在 Sass 中,只有 false
和 null
被看作 Falsy 值,其他都是 Truthy 值,比如,空字符层,0 等值都是 Truthy 值。
# null
null
值也是该类型的唯一值。它表示没有值,通常由函数返回,表示没有结果。
@use "sass:map";
@use "sass:string";
@debug string.index("Helvetica Neue", "Roboto"); // null
@debug map.get(("large": 20px), "small"); // null
@debug &; // null
2
3
4
5
6
如果列表中包含一个空值,则生成的CSS中将省略这个空值。
$fonts: ("serif": "Helvetica Neue", "monospace": "Consolas");
h3 {
font: 18px bold map-get($fonts, "sans");
}
2
3
4
5
生成的 css :
h3 {
font: 18px bold;
}
2
3
如果属性值为空,则完全省略该属性。
$fonts: ("serif": "Helvetica Neue", "monospace": "Consolas");
h3 {
font: {
size: 18px;
weight: bold;
family: map-get($fonts, "sans");
}
}
2
3
4
5
6
7
8
9
编译后的 css :
h3 {
font-size: 18px;
font-weight: bold;
}
2
3
4
← Sass 调试 Sass中的运算操作符 →